<template>
    <div class="channel-select">
        <div class="toolbar">
            <span class="label">选择搜索应用频道：</span>
            <a-button size="small" @click="onCreate">新增</a-button>
        </div>

        <a-table :columns="columns" :data-source="pagedData" :row-selection="rowSelection" :pagination="false"
            size="small" bordered row-key="rowKey" :scroll="{ x: 'max-content' }" class="table" @change="onTableChange"
            :rowClassName="() => 'clickable-row'">
            <template #bodyCell="{ column, record, index }">
                <template v-if="column.dataIndex === 'order'">
                    {{ (page - 1) * pageSize + index + 1 }}
                </template>

                <template v-else-if="column.dataIndex === 'style'">
                    <span class="ellipsis">{{ record.style }}</span>
                    <span v-if="record.styleCount" class="minor">（{{ record.styleCount }}）</span>
                </template>

                <template v-else-if="column.key === 'action'">
                    <a-button type="link" size="small" @click="onView(record)">查看</a-button>
                </template>
            </template>
        </a-table>

        <div class="pager-bar">
            <div class="total">本页 {{ pagedData.length }} 条，共 {{ data.length }} 条。</div>
            <div class="pager-right">
                <a-pagination :current="page" :page-size="pageSize" :total="data.length" :show-less-items="true"
                    @change="onPageChange" />
                <a-select v-model:value="pageSize" size="small" :options="pageSizeOptions" class="page-size-select"
                    @change="onPageSizeChange" />
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { computed, reactive, ref, watch, defineExpose } from 'vue'
import { message } from 'ant-design-vue'
import type { TableColumnType, TableProps } from 'ant-design-vue'
import api from '@/api/api'

type Row = {
    /** 行主键 */
    rowKey: string | number
    /** 用于选择的 id */
    id: string | number
    /** 频道 id */
    channelId: string | number
    appId?: string | number
    name: string
    api: string
    apiType: string | string[]
    style: string
    styleCount?: number
    createdAt: string
}

const props = defineProps<{
    active: boolean
    providedList?: any[] | null
    initialSelectedRowKeys?: (string | number)[]
    initialSelectedIds?: (string | number)[]
    initialSelectedNames?: string[]
    appId?: string | number
}>()

const emit = defineEmits<{
    (e: 'ids-change', ids: (string | number)[]): void
    (e: 'valid-change', v: boolean): void
    (e: 'selected-detail-change', rows: Array<{
        channel_id: string | number
        app_id?: string | number
        channel_name: string
    }>): void
}>()

/** 数据与分页 */
const data = reactive<Row[]>([])
const sorterState = ref<{ field?: string; order?: 'ascend' | 'descend' | null }>({})
const page = ref(1)
const pageSize = ref(10)
const pageSizeOptions = [
    { label: '10条/页', value: 10 },
    { label: '20条/页', value: 20 },
    { label: '50条/页', value: 50 }
]

/** 勾选 */
const selectedRowKeys = ref<(string | number)[]>([])
const rowSelection = computed<TableProps['rowSelection']>(() => ({
    selectedRowKeys: selectedRowKeys.value,
    preserveSelectedRowKeys: true,
    onChange: (keys: (string | number)[]) => { selectedRowKeys.value = keys }
}))

const isValid = computed(() => selectedRowKeys.value.length > 0)

/** —— 构造行 —— */
function mapListToRows(list: any[]): Row[] {
    return (list || []).map((it: any, idx: number) => {
        const channelId = it.channel_id ?? it.id ?? it.app_channel_id ?? `${idx}`
        const appId = it.app_id ?? it.appId
        return {
            rowKey: channelId,
            id: channelId,
            channelId,
            appId,
            name: (it.channel_name ?? it.name ?? '').toString(),
            api: it.search_interface ?? '',
            apiType: it.interface_type ?? '',
            style: it.entry_style ?? '',
            styleCount: undefined,
            createdAt: formatDateTimeCN(it.create_time)
        }
    })
}

/** 工具 */
function formatDateTimeCN(input: any): string {
    if (!input) return ''
    const d = new Date(String(input).replace(/-/g, '/').replace('T', ' '))
    if (Number.isNaN(d.getTime())) return String(input)
    const pad = (n: number) => (n < 10 ? `0${n}` : String(n))
    return `${d.getFullYear()}年${pad(d.getMonth() + 1)}月${pad(d.getDate())}日 ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}

/** 是否已装载数据 */
const hasLoaded = ref(false)

watch(
    () => props.providedList,
    (list) => {
        if (Array.isArray(list)) {
            data.splice(0, data.length, ...mapListToRows(list))
            hasLoaded.value = true
            applySelection()
        }
    },
    { immediate: true, deep: true }
)

/** —— 自行加载 —— */
async function loadChannelList() {
    try {
        const params: any = {}
        if (props.appId !== undefined && props.appId !== null) {
            params.app_id = props.appId
        }
        const res: any = await api.searchAppChannelList(params)
        const list: any[] = (res && res.data) || []
        data.splice(0, data.length, ...mapListToRows(list))
    } catch (e: any) {
        message.error(e?.message || '频道列表加载失败')
    }
}

watch(
    () => props.active,
    async (on) => {
        if (!on || hasLoaded.value) return
        if (!props.providedList || props.providedList.length === 0) {
            await loadChannelList()
            hasLoaded.value = true
            applySelection()
        }
    },
    { immediate: true }
)

watch(
    () => props.appId,
    async (cur, prev) => {
        if (!props.active) return
        if (props.providedList && props.providedList.length) return
        if (cur !== prev) {
            await loadChannelList()
            applySelection()
        }
    }
)

function normalizeName(s: any) {
    return (s == null ? '' : String(s)).trim().toLowerCase()
}

watch(
    () => [props.initialSelectedRowKeys, props.initialSelectedIds, props.initialSelectedNames],
    () => { if (hasLoaded.value) applySelection() },
    { deep: true, immediate: true }
)

function applySelection() {
    if (props.initialSelectedRowKeys && props.initialSelectedRowKeys.length) {
        selectedRowKeys.value = [...props.initialSelectedRowKeys]
        return
    }
    if (props.initialSelectedIds && props.initialSelectedIds.length) {
        const idSet = new Set(props.initialSelectedIds)
        const keys = data.filter(r => idSet.has(r.id)).map(r => r.rowKey)
        if (keys.length) { selectedRowKeys.value = keys; return }
    }
    if (props.initialSelectedNames && props.initialSelectedNames.length) {
        const nameSet = new Set(props.initialSelectedNames.map(normalizeName))
        const keys = data.filter(r => nameSet.has(normalizeName(r.name))).map(r => r.rowKey)
        if (keys.length) { selectedRowKeys.value = keys; return }
    }
}

/** —— 列/分页/排序 —— */
const columns = ref<TableColumnType<Row>[]>([
    { title: '序号', dataIndex: 'order', width: 80, align: 'center' },
    { title: '频道名称', dataIndex: 'name', width: 160 },
    { title: '搜索接口', dataIndex: 'api', width: 260 },
    {
        title: '接口类型',
        dataIndex: 'apiType',
        width: 160,
        sorter: true,
        customRender: ({ text }) => (Array.isArray(text) ? text.join(' & ') : text)
    },
    { title: '词条样式', dataIndex: 'style', width: 180 },
    { title: '创建时间', dataIndex: 'createdAt', sorter: true, width: 200 },
    { title: '操作', key: 'action', width: 120 }
])

const sortedData = computed(() => {
    const { field, order } = sorterState.value
    if (!field || !order) return data
    const list = [...data]
    list.sort((a: any, b: any) => {
        const va = a[field]; const vb = b[field]
        if (va === vb) return 0
        const r = String(va).localeCompare(String(vb))
        return order === 'ascend' ? r : -r
    })
    return list
})
const pagedData = computed(() => {
    const start = (page.value - 1) * pageSize.value
    return sortedData.value.slice(start, start + pageSize.value)
})
function onTableChange(_: any, __: any, sorter: any) { sorterState.value = { field: sorter?.field, order: sorter?.order } }
function onCreate() { }
function onView(_row: Row) { }
function onPageChange(p: number) { page.value = p }
function onPageSizeChange() { page.value = 1 }

/** 选中联动 */
watch(
    selectedRowKeys,
    () => {
        const ids = getSelectedIds()
        emit('ids-change', ids)
        emit('valid-change', isValid.value)
        emit('selected-detail-change', getSelectedDetails().map(r => ({
            channel_id: r.channelId,
            app_id: r.appId,
            channel_name: r.name
        })))
    },
    { immediate: true }
)

/** 对外暴露 */
async function validate() {
    if (!isValid.value) {
        message.error('请至少选择一个频道')
        throw new Error('channel-select: empty selection')
    }
}
function getSelectedRowKeys() { return [...selectedRowKeys.value] }
function getSelectedRows() {
    const set = new Set(selectedRowKeys.value)
    return data.filter(d => set.has(d.rowKey))
}
function getSelectedIds() { return getSelectedRows().map(r => r.id) }
function getSelectedDetails() { return getSelectedRows() }
function setSelection(keysOrIds: (string | number)[]) {
    if (!keysOrIds?.length) { selectedRowKeys.value = []; return }
    const asSet = new Set(keysOrIds)
    const keys: (string | number)[] = []
    data.forEach(d => { if (asSet.has(d.rowKey) || asSet.has(d.id) || asSet.has(d.name)) keys.push(d.rowKey) })
    selectedRowKeys.value = keys
}

defineExpose({
    validate,
    isValid,
    selectedRowKeys,
    getSelectedRowKeys,
    getSelectedRows,
    getSelectedIds,
    getSelectedDetails,
    setSelection
})
</script>

<style scoped lang="less">
.channel-select {
    width: 100%;
}

.toolbar {
    display: flex;
    align-items: center;
    margin-bottom: 8px;

    .label {
        margin-right: 8px;
        font-size: 14px;
    }
}

.table {
    :deep(.ant-table) {
        font-size: 13px;
    }

    :deep(.ant-table-thead > tr > th),
    :deep(.ant-table-tbody > tr > td) {
        padding: 8px 12px;
    }

    :deep(.ant-table-thead > tr > th) {
        background: #F4F8FD !important;
    }

    :deep(.clickable-row) td {
        cursor: default;
    }

    .ellipsis {
        max-width: 180px;
        display: inline-block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .minor {
        color: #999;
    }
}

.pager-bar {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 12px;
    margin-top: 10px;

    .total {
        color: #333;
        font-size: 14px;
        padding-left: 4px;
    }

    .pager-right {
        display: inline-flex;
        align-items: center;
        gap: 12px;
    }

    .page-size-select {
        width: 92px;
    }
}
</style>
